<script setup lang="ts">
import { VueDraggable } from "vue-draggable-plus";
import { computed } from "vue";
import { delField, copyField, deepCopy } from "@/utils/process";
import FormComponent from "./FormComponent.vue";
import type {
  FormDesignerComponents,
  FormItemPerm
} from "../FormComponentMixin";
import type { FormInstance } from "element-plus";
import { isDisplay } from "../FormItem";

const props = defineProps({
  mode: {
    type: String,
    default: "normal"
  },
  type: {
    type: String,
    default: ""
  },
  rules: {
    type: Object,
    default: {}
  }
});

const _value = defineModel<any[]>();
const _active = defineModel<FormDesignerComponents>("active");
const config = defineModel<FormDesignerComponents>("config");
const _this = getCurrentInstance();
const perm = inject<Array<FormItemPerm>>("perm");

const state = reactive({
  rules: props.rules
});

watchEffect(() => {
  state.rules = props.rules;
});

const freeMode = computed(() => props.mode === "free");

const tbCellStyle = {
  background: "#e8e8e8",
  padding: "5px 2px"
};

function onHeaderClick(column, ev) {
  ev.stopPropagation();
  const active = config.value.props.columns[column.no];
  if (active) {
    _active.value = active;
  }
}

function getRow() {
  let row = {};
  config.value.props.columns.forEach(col => (row[col.code] = null));
  return row;
}

function addRow() {
  if (_value && _value.value) {
    _value.value.push(getRow());
  } else {
    _value.value = [getRow()];
  }
}

function delRow(i) {
  _value.value.splice(i, 1);
}

function copyRow(row) {
  const addRow = deepCopy(row);
  addRow.id = "";
  _value.value.push(addRow);
  validate();
}

function validate() {
  const refs = _this.refs[config.value.code + "FormRef"] as FormInstance;
  if (refs) {
    return refs.validate();
  }
}

defineExpose({ validate });
</script>

<template>
  <div class="tablelist-container">
    <el-tabs type="border-card">
      <el-tab-pane>
        <template #label>
          <div style="display: flex; align-items: center">
            <IconifyIconOnline :icon="config.icon" /> {{ config.name }}
          </div>
        </template>
        <vue-draggable
          v-model="config.props.columns"
          target=".w-tb-header-cell"
          group="FormDesign"
          filter=".w-tb-op"
          :animation="150"
          :disabled="!freeMode"
          :ghostClass="freeMode ? 'w-f-cp-select' : ''"
          class="w-f-cp-ct"
        >
          <el-form
            label-width="0px"
            :model="_value"
            :ref="config.code + 'FormRef'"
          >
            <el-table
              :data="_value"
              :cell-style="{ padding: 0 }"
              header-row-class-name="w-tb-header-cell"
              :border="config.props.showBorder"
              :max-height="config.props.height"
              :header-cell-style="tbCellStyle"
              @header-click="onHeaderClick"
            >
              <template v-if="freeMode" #empty>
                <span>👆拖拽字段到上方列内</span>
              </template>
              <template v-for="(col, i) in config.props.columns" :key="i">
                <el-table-column
                  ref="col"
                  :prop="col.code"
                  :label="col.name"
                  :class-name="`${mode === 'free' ? 'w-form-d-item' : ''} ${_active?.id === col.id && freeMode ? 'w-form-cp-active' : ''}`"
                >
                  <template #header>
                    <div
                      style="border: none !important"
                      :class="{
                        'w-form-cp-active': _active?.id === col.id && freeMode
                      }"
                    >
                      <div class="w-form-component" v-if="freeMode">
                        <el-icon
                          @click="copyField(config.props.columns, i)"
                          color="#FFF"
                          ><CopyDocument
                        /></el-icon>
                        <el-icon
                          @click="delField(config.props.columns, i)"
                          color="#FFF"
                          ><Delete
                        /></el-icon>
                      </div>
                      <div>{{ col.name }}</div>
                    </div>
                  </template>
                  <template v-slot="scope">
                    <div class="row-form-item">
                      <el-form-item
                        :prop="'[' + scope.$index + '].' + col.code"
                        :rules="state.rules[col.code]"
                        style="width: 95%"
                      >
                        <div v-if="isDisplay(perm, col.code)">
                          <FormComponent
                            :index="i"
                            :parents="config.props.columns"
                            :mode="props.mode"
                            :config="col"
                            v-model:active="_active"
                            v-model="_value[scope.$index][col.code]"
                            :key="col.id"
                            :type="col.type"
                          />
                        </div>
                      </el-form-item>
                    </div>
                  </template>
                </el-table-column>
              </template>
              <el-table-column
                fixed="right"
                width="100"
                label="操作"
                @click.native="onHeaderClick"
                class-name="w-tb-op"
              >
                <template #header>
                  <span>操作</span>
                  <el-button
                    icon="plus"
                    v-if="mode === 'normal'"
                    size="small"
                    @click="addRow"
                    circle
                    class="w-tb-op-add"
                  />
                </template>
                <template #default="{ scope }">
                  <el-link
                    type="danger"
                    :underline="false"
                    @click="delRow(scope.$index)"
                    >删除</el-link
                  >
                  <el-divider direction="vertical" />
                  <el-link
                    type="primary"
                    :underline="false"
                    @click="copyRow(scope.row)"
                    >复制</el-link
                  >
                </template>
              </el-table-column>
            </el-table>
          </el-form>
        </vue-draggable>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<style lang="scss" scoped>
.tablelist-container {
  .w-f-cp-ct {
    width: 100%;
    height: 100%;
    min-height: 50px;
    background-color: $main-bgc;
  }

  .w-tb-op {
    position: relative;
    .w-tb-op-add {
      position: absolute;
      top: 5px;
      right: 5px;
    }
  }

  :deep(.w-tb-header-cell) {
    cursor: grab;

    .w-form-d-item {
      position: relative;
      padding: 5px;
      margin: 2px;
      border: 1px dashed white;

      &:hover {
        border: 1px dashed #8d8d8d;
      }
    }

    .w-form-cp-active {
      border: 1px dashed var(--el-color-primary) !important;
    }
  }

  .w-f-cp-select {
    border: 1px dashed var(--el-color-primary) !important;
    border-radius: 2px;
  }

  .w-form-component {
    position: absolute;
    right: 0;
    bottom: 0;
    z-index: 9;
    overflow: hidden;
    width: 60px !important;
    border-radius: 5px 0 0 0;

    i {
      width: 30px;
      height: 25px !important;
      padding: 5px;
      cursor: pointer;
      background: var(--el-color-primary);
      &:hover {
        background: var(--el-color-primary-light-3);
      }
    }
  }

  :deep(.el-tabs__content) {
    padding: 5px;
  }

  .row-form-item {
    display: flex;
    align-items: center;
    height: 60px;
    width: 100%;

    .el-form-item {
      margin-bottom: 0px !important;
      width: 100%;

      .el-form-item__content > div {
        width: 95%;
      }
    }
  }
}
</style>
